home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Kasumi / source / triblt.cpp < prev   
Encoding:
C/C++ Source or Header  |  2007-01-08  |  39.2 KB  |  1,540 lines

  1. #include <math.h>
  2. #include <vector>
  3. #include <vd2/system/math.h>
  4. #include <vd2/system/cpuaccel.h>
  5. #include <vd2/Kasumi/pixmap.h>
  6. #include <vd2/Kasumi/pixmaputils.h>
  7. #include <vd2/Kasumi/pixmapops.h>
  8. #include <vd2/Kasumi/triblt.h>
  9.  
  10. namespace {
  11.     uint32 lerp_RGB888(sint32 a, sint32 b, sint32 x) {
  12.         sint32 a_rb    = a & 0xff00ff;
  13.         sint32 a_g    = a & 0x00ff00;
  14.         sint32 b_rb    = b & 0xff00ff;
  15.         sint32 b_g    = b & 0x00ff00;
  16.  
  17.         const uint32 top_rb = (a_rb + (((b_rb - a_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  18.         const uint32 top_g  = (a_g  + (((b_g  - a_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  19.  
  20.         return top_rb + top_g;
  21.     }
  22.  
  23.     uint32 bilerp_RGB888(sint32 a, sint32 b, sint32 c, sint32 d, sint32 x, sint32 y) {
  24.         sint32 a_rb    = a & 0xff00ff;
  25.         sint32 a_g    = a & 0x00ff00;
  26.         sint32 b_rb    = b & 0xff00ff;
  27.         sint32 b_g    = b & 0x00ff00;
  28.         sint32 c_rb    = c & 0xff00ff;
  29.         sint32 c_g    = c & 0x00ff00;
  30.         sint32 d_rb    = d & 0xff00ff;
  31.         sint32 d_g    = d & 0x00ff00;
  32.  
  33.         const uint32 top_rb = (a_rb + (((b_rb - a_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  34.         const uint32 top_g  = (a_g  + (((b_g  - a_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  35.         const uint32 bot_rb = (c_rb + (((d_rb - c_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  36.         const uint32 bot_g  = (c_g  + (((d_g  - c_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  37.  
  38.         const uint32 final_rb = (top_rb + (((bot_rb - top_rb)*y) >> 8)) & 0xff00ff;
  39.         const uint32 final_g  = (top_g  + (((bot_g  - top_g )*y) >> 8)) & 0x00ff00;
  40.  
  41.         return final_rb + final_g;
  42.     }
  43. }
  44.  
  45. namespace {
  46.     enum {
  47.         kTop = 1,
  48.         kBottom = 2,
  49.         kLeft = 4,
  50.         kRight = 8,
  51.         kNear = 16,
  52.         kFar = 32
  53.     };
  54.  
  55.     struct VDTriBltMipInfo {
  56.         const uint32 *mip;
  57.         ptrdiff_t pitch;
  58.         uint32 uvmul, _pad;
  59.     };
  60.  
  61.     struct VDTriBltInfo {
  62.         VDTriBltMipInfo mips[16];
  63.         uint32 *dst;
  64.         const uint32 *src;
  65.         sint32 width;
  66.         const int *cubictab;
  67.     };
  68.  
  69.     struct VDTriBltGenInfo {
  70.         float    u;
  71.         float    v;
  72.         float    rhw;
  73.         float    dudx;
  74.         float    dvdx;
  75.         float    drhwdx;
  76.     };
  77.  
  78.     typedef void (*VDTriBltSpanFunction)(const VDTriBltInfo *);
  79.     typedef void (*VDTriBltGenFunction)(const VDTriBltGenInfo *);
  80.  
  81.     void vd_triblt_span_point(const VDTriBltInfo *pInfo) {
  82.         sint32 w = -pInfo->width;
  83.         uint32 *dst = pInfo->dst + pInfo->width;
  84.         const uint32 *src = pInfo->src;
  85.         const uint32 *texture = pInfo->mips[0].mip;
  86.         const ptrdiff_t texpitch = pInfo->mips[0].pitch;
  87.  
  88.         do {
  89.             dst[w] = vdptroffset(texture, texpitch * src[1])[src[0]];
  90.             src += 2;
  91.         } while(++w);
  92.     }
  93.  
  94.     void vd_triblt_span_bilinear(const VDTriBltInfo *pInfo) {
  95.         sint32 w = -pInfo->width;
  96.         uint32 *dst = pInfo->dst + pInfo->width;
  97.         const uint32 *src = pInfo->src;
  98.         const uint32 *texture = pInfo->mips[0].mip;
  99.         const ptrdiff_t texpitch = pInfo->mips[0].pitch;
  100.  
  101.         do {
  102.             const sint32 u = src[0];
  103.             const sint32 v = src[1];
  104.             src += 2;
  105.             const uint32 *src1 = vdptroffset(texture, texpitch * (v>>8)) + (u>>8);
  106.             const uint32 *src2 = vdptroffset(src1, texpitch);
  107.  
  108.             dst[w] = bilerp_RGB888(src1[0], src1[1], src2[0], src2[1], u&255, v&255);
  109.         } while(++w);
  110.     }
  111.  
  112.     void vd_triblt_span_trilinear(const VDTriBltInfo *pInfo) {
  113.         sint32 w = -pInfo->width;
  114.         uint32 *dst = pInfo->dst + pInfo->width;
  115.         const uint32 *src = pInfo->src;
  116.  
  117.         do {
  118.             sint32 u = src[0];
  119.             sint32 v = src[1];
  120.             const sint32 lambda = src[2];
  121.             src += 3;
  122.  
  123.             const sint32 lod = lambda >> 8;
  124.  
  125.             const uint32 *texture1 = pInfo->mips[lod].mip;
  126.             const ptrdiff_t texpitch1 = pInfo->mips[lod].pitch;
  127.             const uint32 *texture2 = pInfo->mips[lod+1].mip;
  128.             const ptrdiff_t texpitch2 = pInfo->mips[lod+1].pitch;
  129.  
  130.             u >>= lod;
  131.             v >>= lod;
  132.  
  133.             u += 128;
  134.             v += 128;
  135.  
  136.             const uint32 *src1 = vdptroffset(texture1, texpitch1 * (v>>8)) + (u>>8);
  137.             const uint32 *src2 = vdptroffset(src1, texpitch1);
  138.             const uint32 p1 = bilerp_RGB888(src1[0], src1[1], src2[0], src2[1], u&255, v&255);
  139.  
  140.             u += 128;
  141.             v += 128;
  142.  
  143.             const uint32 *src3 = vdptroffset(texture2, texpitch2 * (v>>9)) + (u>>9);
  144.             const uint32 *src4 = vdptroffset(src3, texpitch2);
  145.             const uint32 p2 = bilerp_RGB888(src3[0], src3[1], src4[0], src4[1], (u>>1)&255, (v>>1)&255);
  146.  
  147.             dst[w] = lerp_RGB888(p1, p2, lambda & 255);
  148.         } while(++w);
  149.     }
  150.  
  151. #ifdef _M_IX86
  152.     extern "C" void vdasm_triblt_span_bilinear_mmx(const VDTriBltInfo *pInfo);
  153.     extern "C" void vdasm_triblt_span_trilinear_mmx(const VDTriBltInfo *pInfo);
  154.     extern "C" void vdasm_triblt_span_point(const VDTriBltInfo *pInfo);
  155. #endif
  156.  
  157.     struct VDTriBltTransformedVertex {
  158.         float x, y, z;
  159.         union {
  160.             float w;
  161.             float rhw;
  162.         };
  163.         float r, g, b, a;
  164.         float u, v;
  165.         int outcode;
  166.  
  167.         void interp(const VDTriBltTransformedVertex *v1, const VDTriBltTransformedVertex *v2, float alpha) {
  168.             x = v1->x + alpha * (v2->x - v1->x);
  169.             y = v1->y + alpha * (v2->y - v1->y);
  170.             z = v1->z + alpha * (v2->z - v1->z);
  171.             w = v1->w + alpha * (v2->w - v1->w);
  172.  
  173.             r = v1->r + alpha * (v2->r - v1->r);
  174.             g = v1->g + alpha * (v2->g - v1->g);
  175.             b = v1->b + alpha * (v2->b - v1->b);
  176.             a = v1->a + alpha * (v2->a - v1->a);
  177.  
  178.             u = v1->u + alpha * (v2->u - v1->u);
  179.             v = v1->v + alpha * (v2->v - v1->v);
  180.  
  181.             outcode    = (x < -w ? kLeft : 0)
  182.                     + (x > +w ? kRight : 0)
  183.                     + (y < -w ? kTop : 0)
  184.                     + (y > +w ? kBottom : 0)
  185.                     + (z < -w ? kNear : 0)
  186.                     + (z > +w ? kFar : 0);
  187.         }
  188.     };
  189.  
  190.     void TransformVerts(VDTriBltTransformedVertex *dst, const VDTriBltVertex *src, int nVerts, const float xform[16], float width, float height) {
  191.         const float xflocal[16]={
  192.             xform[ 0],    xform[ 1],    xform[ 2],    xform[ 3],
  193.             xform[ 4],    xform[ 5],    xform[ 6],    xform[ 7],
  194.             xform[ 8],    xform[ 9],    xform[10],    xform[11],
  195.             xform[12],    xform[13],    xform[14],    xform[15],
  196.         };
  197.  
  198.         if (nVerts <= 0)
  199.             return;
  200.  
  201.         do {
  202.             const float x0 = src->x;
  203.             const float y0 = src->y;
  204.             const float z0 = src->z;
  205.  
  206.             const float w    = x0*xflocal[12] + y0*xflocal[13] + z0*xflocal[14] + xflocal[15];
  207.             const float x   = x0*xflocal[ 0] + y0*xflocal[ 1] + z0*xflocal[ 2] + xflocal[ 3];
  208.             const float y   = x0*xflocal[ 4] + y0*xflocal[ 5] + z0*xflocal[ 6] + xflocal[ 7];
  209.             const float z   = x0*xflocal[ 8] + y0*xflocal[ 9] + z0*xflocal[10] + xflocal[11];
  210.  
  211.             int outcode = 0;
  212.  
  213.             if (x < -w)        outcode += kLeft;
  214.             if (x > w)        outcode += kRight;
  215.             if (y < -w)        outcode += kTop;
  216.             if (y > w)        outcode += kBottom;
  217.             if (z < -w)        outcode += kNear;
  218.             if (z > w)        outcode += kFar;
  219.  
  220.             dst->x = x;
  221.             dst->y = y;
  222.             dst->z = z;
  223.             dst->w = w;
  224.             dst->u = src->u;
  225.             dst->v = src->v;
  226.             dst->r = 1.0f;
  227.             dst->g = 1.0f;
  228.             dst->b = 1.0f;
  229.             dst->a = 1.0f;
  230.             dst->outcode = outcode;
  231.  
  232.             ++src;
  233.             ++dst;
  234.         } while(--nVerts);
  235.     }
  236.  
  237.     void TransformVerts(VDTriBltTransformedVertex *dst, const VDTriColorVertex *src, int nVerts, const float xform[16], float width, float height) {
  238.         const float xflocal[16]={
  239.             xform[ 0],    xform[ 1],    xform[ 2],    xform[ 3],
  240.             xform[ 4],    xform[ 5],    xform[ 6],    xform[ 7],
  241.             xform[ 8],    xform[ 9],    xform[10],    xform[11],
  242.             xform[12],    xform[13],    xform[14],    xform[15],
  243.         };
  244.  
  245.         if (nVerts <= 0)
  246.             return;
  247.  
  248.         do {
  249.             const float x0 = src->x;
  250.             const float y0 = src->y;
  251.             const float z0 = src->z;
  252.  
  253.             const float w    = x0*xflocal[12] + y0*xflocal[13] + z0*xflocal[14] + xflocal[15];
  254.             const float x   = x0*xflocal[ 0] + y0*xflocal[ 1] + z0*xflocal[ 2] + xflocal[ 3];
  255.             const float y   = x0*xflocal[ 4] + y0*xflocal[ 5] + z0*xflocal[ 6] + xflocal[ 7];
  256.             const float z   = x0*xflocal[ 8] + y0*xflocal[ 9] + z0*xflocal[10] + xflocal[11];
  257.  
  258.             int outcode = 0;
  259.  
  260.             if (x < -w)        outcode += kLeft;
  261.             if (x > w)        outcode += kRight;
  262.             if (y < -w)        outcode += kTop;
  263.             if (y > w)        outcode += kBottom;
  264.             if (z < -w)        outcode += kNear;
  265.             if (z > w)        outcode += kFar;
  266.  
  267.             dst->x = x;
  268.             dst->y = y;
  269.             dst->z = z;
  270.             dst->w = w;
  271.             dst->u = 0.0f;
  272.             dst->v = 0.0f;
  273.             dst->r = src->r;
  274.             dst->g = src->g;
  275.             dst->b = src->b;
  276.             dst->a = src->a;
  277.             dst->outcode = outcode;
  278.  
  279.             ++src;
  280.             ++dst;
  281.         } while(--nVerts);
  282.     }
  283.  
  284.     struct VDTriangleSetupInfo {
  285.         const VDTriBltTransformedVertex *pt, *pr, *pl;
  286.         VDTriBltTransformedVertex tmp0, tmp1, tmp2;
  287.     };
  288.  
  289.     void SetupTri(
  290.             VDTriangleSetupInfo& setup,
  291.             VDPixmap& dst,
  292.             const VDTriBltTransformedVertex *vx0,
  293.             const VDTriBltTransformedVertex *vx1,
  294.             const VDTriBltTransformedVertex *vx2,
  295.             const VDTriBltFilterMode *filterMode
  296.             )
  297.     {
  298.         setup.tmp0 = *vx0;
  299.         setup.tmp1 = *vx1;
  300.         setup.tmp2 = *vx2;
  301.  
  302.         // adjust UVs for filter mode
  303.         if (filterMode) {
  304.             switch(*filterMode) {
  305.             case kTriBltFilterBilinear:
  306.                 setup.tmp0.u += 0.5f;
  307.                 setup.tmp0.v += 0.5f;
  308.                 setup.tmp1.u += 0.5f;
  309.                 setup.tmp1.v += 0.5f;
  310.                 setup.tmp2.u += 0.5f;
  311.                 setup.tmp2.v += 0.5f;
  312.             case kTriBltFilterTrilinear:
  313.                 setup.tmp0.u *= 256.0f;
  314.                 setup.tmp0.v *= 256.0f;
  315.                 setup.tmp1.u *= 256.0f;
  316.                 setup.tmp1.v *= 256.0f;
  317.                 setup.tmp2.u *= 256.0f;
  318.                 setup.tmp2.v *= 256.0f;
  319.                 break;
  320.             case kTriBltFilterPoint:
  321.                 setup.tmp0.u += 1.0f;
  322.                 setup.tmp0.v += 1.0f;
  323.                 setup.tmp1.u += 1.0f;
  324.                 setup.tmp1.v += 1.0f;
  325.                 setup.tmp2.u += 1.0f;
  326.                 setup.tmp2.v += 1.0f;
  327.                 break;
  328.             }
  329.         }
  330.  
  331.         // do perspective divide and NDC space conversion
  332.         const float xscale = dst.w * 0.5f;
  333.         const float yscale = dst.h * 0.5f;
  334.  
  335.         setup.tmp0.rhw = 1.0f / setup.tmp0.w;
  336.         setup.tmp0.x = (1.0f+setup.tmp0.x*setup.tmp0.rhw)*xscale;
  337.         setup.tmp0.y = (1.0f+setup.tmp0.y*setup.tmp0.rhw)*yscale;
  338.         setup.tmp0.u *= setup.tmp0.rhw;
  339.         setup.tmp0.v *= setup.tmp0.rhw;
  340.         setup.tmp0.r *= setup.tmp0.rhw;
  341.         setup.tmp0.g *= setup.tmp0.rhw;
  342.         setup.tmp0.b *= setup.tmp0.rhw;
  343.         setup.tmp0.a *= setup.tmp0.rhw;
  344.         setup.tmp1.rhw = 1.0f / setup.tmp1.w;
  345.         setup.tmp1.x = (1.0f+setup.tmp1.x*setup.tmp1.rhw)*xscale;
  346.         setup.tmp1.y = (1.0f+setup.tmp1.y*setup.tmp1.rhw)*yscale;
  347.         setup.tmp1.u *= setup.tmp1.rhw;
  348.         setup.tmp1.v *= setup.tmp1.rhw;
  349.         setup.tmp1.r *= setup.tmp1.rhw;
  350.         setup.tmp1.g *= setup.tmp1.rhw;
  351.         setup.tmp1.b *= setup.tmp1.rhw;
  352.         setup.tmp1.a *= setup.tmp1.rhw;
  353.         setup.tmp2.rhw = 1.0f / setup.tmp2.w;
  354.         setup.tmp2.x = (1.0f+setup.tmp2.x*setup.tmp2.rhw)*xscale;
  355.         setup.tmp2.y = (1.0f+setup.tmp2.y*setup.tmp2.rhw)*yscale;
  356.         setup.tmp2.u *= setup.tmp2.rhw;
  357.         setup.tmp2.v *= setup.tmp2.rhw;
  358.         setup.tmp2.r *= setup.tmp2.rhw;
  359.         setup.tmp2.g *= setup.tmp2.rhw;
  360.         setup.tmp2.b *= setup.tmp2.rhw;
  361.         setup.tmp2.a *= setup.tmp2.rhw;
  362.  
  363.         // verify clipping
  364.         VDASSERT(setup.tmp0.x >= 0 && setup.tmp0.x <= dst.w);
  365.         VDASSERT(setup.tmp1.x >= 0 && setup.tmp1.x <= dst.w);
  366.         VDASSERT(setup.tmp2.x >= 0 && setup.tmp2.x <= dst.w);
  367.         VDASSERT(setup.tmp0.y >= 0 && setup.tmp0.y <= dst.h);
  368.         VDASSERT(setup.tmp1.y >= 0 && setup.tmp1.y <= dst.h);
  369.         VDASSERT(setup.tmp2.y >= 0 && setup.tmp2.y <= dst.h);
  370.  
  371.         vx0 = &setup.tmp0;
  372.         vx1 = &setup.tmp1;
  373.         vx2 = &setup.tmp2;
  374.  
  375.         const VDTriBltTransformedVertex *pt, *pl, *pr;
  376.  
  377.         // sort points
  378.         if (vx0->y < vx1->y)        // 1 < 2
  379.             if (vx0->y < vx2->y) {    // 1 < 2,3
  380.                 pt = vx0;
  381.                 pr = vx1;
  382.                 pl = vx2;
  383.             } else {                // 3 < 1 < 2
  384.                 pt = vx2;
  385.                 pr = vx0;
  386.                 pl = vx1;
  387.             }
  388.         else                        // 2 < 1
  389.             if (vx1->y < vx2->y) {    // 2 < 1,3
  390.                 pt = vx1;
  391.                 pr = vx2;
  392.                 pl = vx0;
  393.             } else {                // 3 < 2 < 1
  394.                 pt = vx2;
  395.                 pr = vx0;
  396.                 pl = vx1;
  397.             }
  398.  
  399.         setup.pl = pl;
  400.         setup.pt = pt;
  401.         setup.pr = pr;
  402.     }
  403.  
  404.     void RenderTri(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  405.                             const VDTriBltTransformedVertex *vx0,
  406.                             const VDTriBltTransformedVertex *vx1,
  407.                             const VDTriBltTransformedVertex *vx2,
  408.                             VDTriBltFilterMode filterMode,
  409.                             bool border)
  410.     {
  411.  
  412.         VDTriangleSetupInfo setup;
  413.  
  414.         SetupTri(setup, dst, vx0, vx1, vx2, &filterMode);
  415.  
  416.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  417.  
  418.         const float x10 = pl->x - pt->x;
  419.         const float x20 = pr->x - pt->x;
  420.         const float y10 = pl->y - pt->y;
  421.         const float y20 = pr->y - pt->y;
  422.         const float A = x20*y10 - x10*y20;
  423.  
  424.         if (A <= 0.f)
  425.             return;
  426.  
  427.         float invA = 0.f;
  428.         if (A >= 1e-5f)
  429.             invA = 1.0f / A;
  430.  
  431.         float x10_A = x10 * invA;
  432.         float x20_A = x20 * invA;
  433.         float y10_A = y10 * invA;
  434.         float y20_A = y20 * invA;
  435.  
  436.         float u10 = pl->u - pt->u;
  437.         float u20 = pr->u - pt->u;
  438.         float v10 = pl->v - pt->v;
  439.         float v20 = pr->v - pt->v;
  440.         float rhw10 = pl->rhw - pt->rhw;
  441.         float rhw20 = pr->rhw - pt->rhw;
  442.  
  443.         float dudx = u20*y10_A - u10*y20_A;
  444.         float dudy = u10*x20_A - u20*x10_A;
  445.         float dvdx = v20*y10_A - v10*y20_A;
  446.         float dvdy = v10*x20_A - v20*x10_A;
  447.         float drhwdx = rhw20*y10_A - rhw10*y20_A;
  448.         float drhwdy = rhw10*x20_A - rhw20*x10_A;
  449.  
  450.         // Compute edge walking parameters
  451.  
  452.         float dxl1=0, dxr1=0, dul1=0, dvl1=0, drhwl1=0;
  453.         float dxl2=0, dxr2=0, dul2=0, dvl2=0, drhwl2=0;
  454.  
  455.         // Compute left-edge interpolation parameters for first half.
  456.  
  457.         if (pl->y != pt->y) {
  458.             dxl1 = (pl->x - pt->x) / (pl->y - pt->y);
  459.  
  460.             dul1 = dudy + dxl1 * dudx;
  461.             dvl1 = dvdy + dxl1 * dvdx;
  462.             drhwl1 = drhwdy + dxl1 * drhwdx;
  463.         }
  464.  
  465.         // Compute right-edge interpolation parameters for first half.
  466.  
  467.         if (pr->y != pt->y) {
  468.             dxr1 = (pr->x - pt->x) / (pr->y - pt->y);
  469.         }
  470.  
  471.         // Compute third-edge interpolation parameters.
  472.  
  473.         if (pr->y != pl->y) {
  474.             dxl2 = (pr->x - pl->x) / (pr->y - pl->y);
  475.  
  476.             dul2 = dudy + dxl2 * dudx;
  477.             dvl2 = dvdy + dxl2 * dvdx;
  478.             drhwl2 = drhwdy + dxl2 * drhwdx;
  479.  
  480.             dxr2 = dxl2;
  481.         }
  482.  
  483.         // Initialize parameters for first half.
  484.         //
  485.         // We place pixel centers at (x+0.5, y+0.5).
  486.  
  487.         double xl, xr, ul, vl, rhwl, yf;
  488.         int y, y1, y2;
  489.  
  490.         // y_start < y+0.5 to include pixel y.
  491.  
  492.         y = (int)floor(pt->y + 0.5);
  493.         yf = (y+0.5) - pt->y;
  494.  
  495.         xl = pt->x + dxl1 * yf;
  496.         xr = pt->x + dxr1 * yf;
  497.         ul = pt->u + dul1 * yf;
  498.         vl = pt->v + dvl1 * yf;
  499.         rhwl = pt->rhw + drhwl1 * yf;
  500.  
  501.         // Initialize parameters for second half.
  502.  
  503.         double xl2, xr2, ul2, vl2, rhwl2;
  504.  
  505.         if (pl->y > pr->y) {        // Left edge is long side
  506.             dxl2 = dxl1;
  507.             dul2 = dul1;
  508.             dvl2 = dvl1;
  509.             drhwl2 = drhwl1;
  510.  
  511.             y1 = (int)floor(pr->y + 0.5);
  512.             y2 = (int)floor(pl->y + 0.5);
  513.  
  514.             yf = (y1+0.5) - pr->y;
  515.  
  516.             // Step left edge.
  517.  
  518.             xl2 = xl + dxl1 * (y1 - y);
  519.             ul2 = ul + dul1 * (y1 - y);
  520.             vl2 = vl + dvl1 * (y1 - y);
  521.             rhwl2 = rhwl + drhwl1 * (y1 - y);
  522.  
  523.             // Prestep right edge.
  524.  
  525.             xr2 = pr->x + dxr2 * yf;
  526.         } else {                    // Right edge is long side
  527.             dxr2 = dxr1;
  528.  
  529.             y1 = (int)floor(pl->y + 0.5);
  530.             y2 = (int)floor(pr->y + 0.5);
  531.  
  532.             yf = (y1+0.5) - pl->y;
  533.  
  534.             // Prestep left edge.
  535.  
  536.             xl2 = pl->x + dxl2 * yf;
  537.             ul2 = pl->u + dul2 * yf;
  538.             vl2 = pl->v + dvl2 * yf;
  539.             rhwl2 = pl->rhw + drhwl2 * yf;
  540.  
  541.             // Step right edge.
  542.  
  543.             xr2 = xr + dxr1 * (y1 - y);
  544.         }
  545.  
  546.         // rasterize
  547.         const ptrdiff_t dstpitch = dst.pitch;
  548.         uint32 *dstp = (uint32 *)((char *)dst.data + dstpitch * y);
  549.  
  550.         VDTriBltInfo texinfo;
  551.         VDTriBltSpanFunction drawSpan;
  552.         uint32 cpuflags = CPUGetEnabledExtensions();
  553.  
  554.         bool triBlt16 = false;
  555.  
  556.         switch(filterMode) {
  557.         case kTriBltFilterTrilinear:
  558. #ifdef _M_IX86
  559.             if (cpuflags & CPUF_SUPPORTS_MMX) {
  560.                 drawSpan = vdasm_triblt_span_trilinear_mmx;
  561.                 triBlt16 = true;
  562.             } else
  563. #endif
  564.                 drawSpan = vd_triblt_span_trilinear;
  565.             break;
  566.         case kTriBltFilterBilinear:
  567. #ifdef _M_IX86
  568.             if (cpuflags & CPUF_SUPPORTS_MMX) {
  569.                 drawSpan = vdasm_triblt_span_bilinear_mmx;
  570.                 triBlt16 = true;
  571.             } else
  572. #endif
  573.                 drawSpan = vd_triblt_span_bilinear;
  574.             break;
  575.         case kTriBltFilterPoint:
  576.             drawSpan = vd_triblt_span_point;
  577.             break;
  578.         }
  579.  
  580.         float rhobase = sqrt(std::max<float>(dudx*dudx + dvdx*dvdx, dudy*dudy + dvdy*dvdy) * (1.0f / 65536.0f));
  581.  
  582.         if (triBlt16) {
  583.             ul *= 256.0f;
  584.             vl *= 256.0f;
  585.             ul2 *= 256.0f;
  586.             vl2 *= 256.0f;
  587.             dul1 *= 256.0f;
  588.             dvl1 *= 256.0f;
  589.             dul2 *= 256.0f;
  590.             dvl2 *= 256.0f;
  591.             dudx *= 256.0f;
  592.             dvdx *= 256.0f;
  593.             dudy *= 256.0f;
  594.             dvdy *= 256.0f;
  595.         }
  596.  
  597.         int minx1 = (int)floor(std::min<float>(std::min<float>(pl->x, pr->x), pt->x) + 0.5);
  598.         int maxx2 = (int)floor(std::max<float>(std::max<float>(pl->x, pr->x), pt->x) + 0.5);
  599.  
  600.         uint32 *const spanptr = new uint32[3 * (maxx2 - minx1)];
  601.  
  602.         while(y < y2) {
  603.             if (y == y1) {
  604.                 xl = xl2;
  605.                 xr = xr2;
  606.                 ul = ul2;
  607.                 vl = vl2;
  608.                 rhwl = rhwl2;
  609.                 dxl1 = dxl2;
  610.                 dxr1 = dxr2;
  611.                 dul1 = dul2;
  612.                 dvl1 = dvl2;
  613.                 drhwl1 = drhwl2;
  614.             }
  615.  
  616.             int x1, x2;
  617.             double xf;
  618.             double u, v, rhw;
  619.  
  620.             // x_left must be less than (x+0.5) to include pixel x.
  621.  
  622.             x1        = (int)floor(xl + 0.5);
  623.             x2        = (int)floor(xr + 0.5);
  624.             xf        = (x1+0.5) - xl;
  625.             
  626.             u        = ul + xf * dudx;
  627.             v        = vl + xf * dvdx;
  628.             rhw        = rhwl + xf * drhwdx;
  629.  
  630.             int x = x1;
  631.             uint32 *spanp = spanptr;
  632.  
  633.             float w = 1.0f / (float)rhw;
  634.  
  635.             if (x < x2) {
  636.                 if (filterMode >= kTriBltFilterTrilinear) {
  637.                     do {
  638.                         int utexel = VDRoundToIntFastFullRange(u * w);
  639.                         int vtexel = VDRoundToIntFastFullRange(v * w);
  640.                         union{ float f; sint32 i; } rho = {rhobase * w};
  641.  
  642.                         int lambda = ((rho.i - 0x3F800000) >> (23-8));
  643.                         if (lambda < 0)
  644.                             lambda = 0;
  645.                         if (lambda >= (nMipmaps<<8)-256)
  646.                             lambda = (nMipmaps<<8)-257;
  647.  
  648.                         spanp[0] = utexel;
  649.                         spanp[1] = vtexel;
  650.                         spanp[2] = lambda;
  651.                         spanp += 3;
  652.  
  653.                         u += dudx;
  654.                         v += dvdx;
  655.                         rhw += drhwdx;
  656.  
  657.                         w *= (2.0f - w*(float)rhw);
  658.                     } while(++x < x2);
  659.                 } else {
  660.                     do {
  661.                         int utexel = VDFloorToInt(u * w);
  662.                         int vtexel = VDFloorToInt(v * w);
  663.  
  664.                         spanp[0] = utexel;
  665.                         spanp[1] = vtexel;
  666.                         spanp += 2;
  667.  
  668.                         u += dudx;
  669.                         v += dvdx;
  670.                         rhw += drhwdx;
  671.  
  672.                         w *= (2.0f - w*(float)rhw);
  673.                     } while(++x < x2);
  674.                 }
  675.             }
  676.  
  677.             for(int i=0; i<nMipmaps; ++i) {
  678.                 texinfo.mips[i].mip        = (const uint32 *)pSources[i]->data;
  679.                 texinfo.mips[i].pitch    = pSources[i]->pitch;
  680.                 texinfo.mips[i].uvmul    = (pSources[i]->pitch << 16) + 4;
  681.             }
  682.             texinfo.dst = dstp+x1;
  683.             texinfo.src = spanptr;
  684.             texinfo.width = x2-x1;
  685.  
  686.             if (texinfo.width>0)
  687.                 drawSpan(&texinfo);
  688.  
  689.             dstp = vdptroffset(dstp, dstpitch);
  690.             xl += dxl1;
  691.             xr += dxr1;
  692.             ul += dul1;
  693.             vl += dvl1;
  694.             rhwl += drhwl1;
  695.  
  696.             ++y;
  697.         }
  698.  
  699.         delete[] spanptr;
  700.     }
  701.  
  702.     void FillTri(VDPixmap& dst, uint32 c,
  703.                     const VDTriBltTransformedVertex *vx0,
  704.                     const VDTriBltTransformedVertex *vx1,
  705.                     const VDTriBltTransformedVertex *vx2
  706.                     )
  707.     {
  708.  
  709.         VDTriangleSetupInfo setup;
  710.  
  711.         SetupTri(setup, dst, vx0, vx1, vx2, NULL);
  712.  
  713.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  714.  
  715.         // Compute edge walking parameters
  716.         float dxl1=0, dxr1=0;
  717.         float dxl2=0, dxr2=0;
  718.  
  719.         float x_lt = pl->x - pt->x;
  720.         float x_rt = pr->x - pt->x;
  721.         float x_rl = pr->x - pl->x;
  722.         float y_lt = pl->y - pt->y;
  723.         float y_rt = pr->y - pt->y;
  724.         float y_rl = pr->y - pl->y;
  725.  
  726.         // reject backfaces
  727.         if (x_lt*y_rt >= x_rt*y_lt)
  728.             return;
  729.  
  730.         // Compute left-edge interpolation parameters for first half.
  731.         if (pl->y != pt->y)
  732.             dxl1 = x_lt / y_lt;
  733.  
  734.         // Compute right-edge interpolation parameters for first half.
  735.         if (pr->y != pt->y)
  736.             dxr1 = x_rt / y_rt;
  737.  
  738.         // Compute third-edge interpolation parameters.
  739.         if (pr->y != pl->y) {
  740.             dxl2 = x_rl / y_rl;
  741.  
  742.             dxr2 = dxl2;
  743.         }
  744.  
  745.         // Initialize parameters for first half.
  746.         //
  747.         // We place pixel centers at (x+0.5, y+0.5).
  748.  
  749.         double xl, xr, yf;
  750.         int y, y1, y2;
  751.  
  752.         // y_start < y+0.5 to include pixel y.
  753.  
  754.         y = (int)floor(pt->y + 0.5);
  755.         yf = (y+0.5) - pt->y;
  756.  
  757.         xl = pt->x + dxl1 * yf;
  758.         xr = pt->x + dxr1 * yf;
  759.  
  760.         // Initialize parameters for second half.
  761.         double xl2, xr2;
  762.  
  763.         if (pl->y > pr->y) {        // Left edge is long side
  764.             dxl2 = dxl1;
  765.  
  766.             y1 = (int)floor(pr->y + 0.5);
  767.             y2 = (int)floor(pl->y + 0.5);
  768.  
  769.             yf = (y1+0.5) - pr->y;
  770.  
  771.             // Prestep right edge.
  772.             xr2 = pr->x + dxr2 * yf;
  773.  
  774.             // Step left edge.
  775.             xl2 = xl + dxl1 * (y1 - y);
  776.         } else {                    // Right edge is long side
  777.             dxr2 = dxr1;
  778.  
  779.             y1 = (int)floor(pl->y + 0.5);
  780.             y2 = (int)floor(pr->y + 0.5);
  781.  
  782.             yf = (y1+0.5) - pl->y;
  783.  
  784.             // Prestep left edge.
  785.             xl2 = pl->x + dxl2 * yf;
  786.  
  787.             // Step right edge.
  788.             xr2 = xr + dxr1 * (y1 - y);
  789.         }
  790.  
  791.         // rasterize
  792.         const ptrdiff_t dstpitch = dst.pitch;
  793.         uint32 *dstp = (uint32 *)((char *)dst.data + dstpitch * y);
  794.  
  795.         while(y < y2) {
  796.             if (y == y1) {
  797.                 xl = xl2;
  798.                 xr = xr2;
  799.                 dxl1 = dxl2;
  800.                 dxr1 = dxr2;
  801.             }
  802.  
  803.             int x1, x2;
  804.             double xf;
  805.  
  806.             // x_left must be less than (x+0.5) to include pixel x.
  807.  
  808.             x1        = (int)floor(xl + 0.5);
  809.             x2        = (int)floor(xr + 0.5);
  810.             xf        = (x1+0.5) - xl;
  811.             
  812.             while(x1 < x2)
  813.                 dstp[x1++] = c;
  814.  
  815.             dstp = vdptroffset(dstp, dstpitch);
  816.             xl += dxl1;
  817.             xr += dxr1;
  818.             ++y;
  819.         }
  820.     }
  821.  
  822.     void FillTriGrad(VDPixmap& dst,
  823.                     const VDTriBltTransformedVertex *vx0,
  824.                     const VDTriBltTransformedVertex *vx1,
  825.                     const VDTriBltTransformedVertex *vx2
  826.                     )
  827.     {
  828.  
  829.         VDTriangleSetupInfo setup;
  830.  
  831.         SetupTri(setup, dst, vx0, vx1, vx2, NULL);
  832.  
  833.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  834.         const float x10 = pl->x - pt->x;
  835.         const float x20 = pr->x - pt->x;
  836.         const float y10 = pl->y - pt->y;
  837.         const float y20 = pr->y - pt->y;
  838.         const float A = x20*y10 - x10*y20;
  839.  
  840.         if (A <= 0.f)
  841.             return;
  842.  
  843.         float invA = 0.f;
  844.         if (A >= 1e-5f)
  845.             invA = 1.0f / A;
  846.  
  847.         float x10_A = x10 * invA;
  848.         float x20_A = x20 * invA;
  849.         float y10_A = y10 * invA;
  850.         float y20_A = y20 * invA;
  851.  
  852.         float r10 = pl->r - pt->r;
  853.         float r20 = pr->r - pt->r;
  854.         float g10 = pl->g - pt->g;
  855.         float g20 = pr->g - pt->g;
  856.         float b10 = pl->b - pt->b;
  857.         float b20 = pr->b - pt->b;
  858.         float a10 = pl->a - pt->a;
  859.         float a20 = pr->a - pt->a;
  860.         float rhw10 = pl->rhw - pt->rhw;
  861.         float rhw20 = pr->rhw - pt->rhw;
  862.  
  863.         float drdx = r20*y10_A - r10*y20_A;
  864.         float drdy = r10*x20_A - r20*x10_A;
  865.         float dgdx = g20*y10_A - g10*y20_A;
  866.         float dgdy = g10*x20_A - g20*x10_A;
  867.         float dbdx = b20*y10_A - b10*y20_A;
  868.         float dbdy = b10*x20_A - b20*x10_A;
  869.         float dadx = a20*y10_A - a10*y20_A;
  870.         float dady = a10*x20_A - a20*x10_A;
  871.         float drhwdx = rhw20*y10_A - rhw10*y20_A;
  872.         float drhwdy = rhw10*x20_A - rhw20*x10_A;
  873.  
  874.         // Compute edge walking parameters
  875.         float dxl1=0;
  876.         float drl1=0;
  877.         float dgl1=0;
  878.         float dbl1=0;
  879.         float dal1=0;
  880.         float drhwl1=0;
  881.         float dxr1=0;
  882.         float dxl2=0;
  883.         float drl2=0;
  884.         float dgl2=0;
  885.         float dbl2=0;
  886.         float dal2=0;
  887.         float drhwl2=0;
  888.         float dxr2=0;
  889.  
  890.         float x_lt = pl->x - pt->x;
  891.         float x_rt = pr->x - pt->x;
  892.         float x_rl = pr->x - pl->x;
  893.         float y_lt = pl->y - pt->y;
  894.         float y_rt = pr->y - pt->y;
  895.         float y_rl = pr->y - pl->y;
  896.  
  897.         // Compute left-edge interpolation parameters for first half.
  898.         if (pl->y != pt->y) {
  899.             dxl1 = x_lt / y_lt;
  900.             drl1 = drdy + dxl1 * drdx;
  901.             dgl1 = dgdy + dxl1 * dgdx;
  902.             dbl1 = dbdy + dxl1 * dbdx;
  903.             dal1 = dady + dxl1 * dadx;
  904.             drhwl1 = drhwdy + dxl1 * drhwdx;
  905.         }
  906.  
  907.         // Compute right-edge interpolation parameters for first half.
  908.         if (pr->y != pt->y)
  909.             dxr1 = x_rt / y_rt;
  910.  
  911.         // Compute third-edge interpolation parameters.
  912.         if (pr->y != pl->y) {
  913.             dxl2 = x_rl / y_rl;
  914.  
  915.             drl2 = drdy + dxl2 * drdx;
  916.             dgl2 = dgdy + dxl2 * dgdx;
  917.             dbl2 = dbdy + dxl2 * dbdx;
  918.             dal2 = dady + dxl2 * dadx;
  919.             drhwl2 = drhwdy + dxl2 * drhwdx;
  920.  
  921.             dxr2 = dxl2;
  922.         }
  923.  
  924.         // Initialize parameters for first half.
  925.         //
  926.         // We place pixel centers at (x+0.5, y+0.5).
  927.  
  928.         double xl, xr, yf;
  929.         double rl, gl, bl, al, rhwl;
  930.         double rl2, gl2, bl2, al2, rhwl2;
  931.         int y, y1, y2;
  932.  
  933.         // y_start < y+0.5 to include pixel y.
  934.  
  935.         y = (int)floor(pt->y + 0.5);
  936.         yf = (y+0.5) - pt->y;
  937.  
  938.         xl = pt->x + dxl1 * yf;
  939.         xr = pt->x + dxr1 * yf;
  940.         rl = pt->r + drl1 * yf;
  941.         gl = pt->g + dgl1 * yf;
  942.         bl = pt->b + dbl1 * yf;
  943.         al = pt->a + dal1 * yf;
  944.         rhwl = pt->rhw + drhwl1 * yf;
  945.  
  946.         // Initialize parameters for second half.
  947.         double xl2, xr2;
  948.  
  949.         if (pl->y > pr->y) {        // Left edge is long side
  950.             dxl2 = dxl1;
  951.             drl2 = drl1;
  952.             dgl2 = dgl1;
  953.             dbl2 = dbl1;
  954.             dal2 = dal1;
  955.             drhwl2 = drhwl1;
  956.  
  957.             y1 = (int)floor(pr->y + 0.5);
  958.             y2 = (int)floor(pl->y + 0.5);
  959.  
  960.             yf = (y1+0.5) - pr->y;
  961.  
  962.             // Step left edge.
  963.             xl2 = xl + dxl1 * (y1 - y);
  964.             rl2 = rl + drl1 * (y1 - y);
  965.             gl2 = gl + dgl1 * (y1 - y);
  966.             bl2 = bl + dbl1 * (y1 - y);
  967.             al2 = al + dal1 * (y1 - y);
  968.             rhwl2 = rhwl + drhwl1 * (y1 - y);
  969.  
  970.             // Prestep right edge.
  971.             xr2 = pr->x + dxr2 * yf;
  972.         } else {                    // Right edge is long side
  973.             dxr2 = dxr1;
  974.  
  975.             y1 = (int)floor(pl->y + 0.5);
  976.             y2 = (int)floor(pr->y + 0.5);
  977.  
  978.             yf = (y1+0.5) - pl->y;
  979.  
  980.             // Prestep left edge.
  981.             xl2 = pl->x + dxl2 * yf;
  982.             rl2 = pl->r + drl2 * yf;
  983.             gl2 = pl->g + dgl2 * yf;
  984.             bl2 = pl->b + dbl2 * yf;
  985.             al2 = pl->a + dal2 * yf;
  986.             rhwl2 = pl->rhw + drhwl2 * yf;
  987.  
  988.             // Step right edge.
  989.             xr2 = xr + dxr2 * (y1 - y);
  990.         }
  991.  
  992.         // rasterize
  993.         const ptrdiff_t dstpitch = dst.pitch;
  994.         char *dstp0 = (char *)dst.data + dstpitch * y;
  995.  
  996.         while(y < y2) {
  997.             if (y == y1) {
  998.                 xl = xl2;
  999.                 xr = xr2;
  1000.                 rl = rl2;
  1001.                 gl = gl2;
  1002.                 bl = bl2;
  1003.                 al = al2;
  1004.                 rhwl = rhwl2;
  1005.                 dxl1 = dxl2;
  1006.                 drl1 = drl2;
  1007.                 dgl1 = dgl2;
  1008.                 dbl1 = dbl2;
  1009.                 dal1 = dal2;
  1010.                 drhwl1 = drhwl2;
  1011.                 dxr1 = dxr2;
  1012.             }
  1013.  
  1014.             int x1, x2;
  1015.             double xf;
  1016.             double r, g, b, a, rhw;
  1017.  
  1018.             // x_left must be less than (x+0.5) to include pixel x.
  1019.  
  1020.             x1        = (int)floor(xl + 0.5);
  1021.             x2        = (int)floor(xr + 0.5);
  1022.             xf        = (x1+0.5) - xl;
  1023.             
  1024.             r        = rl + xf * drdx;
  1025.             g        = gl + xf * dgdx;
  1026.             b        = bl + xf * dbdx;
  1027.             a        = al + xf * dadx;
  1028.             rhw        = rhwl + xf * drhwdx;
  1029.  
  1030.             float w = 1.0f / (float)rhw;
  1031.  
  1032.             if (x1 < x2) {
  1033.                 if (dst.format == nsVDPixmap::kPixFormat_XRGB8888) {
  1034.                     uint32 *dstp = (uint32 *)dstp0;
  1035.  
  1036.                     do {
  1037.                         float sr = (float)(r * w);
  1038.                         float sg = (float)(g * w);
  1039.                         float sb = (float)(b * w);
  1040.                         float sa = (float)(a * w);
  1041.  
  1042.                         uint8 ir = VDClampedRoundFixedToUint8Fast(sr);
  1043.                         uint8 ig = VDClampedRoundFixedToUint8Fast(sg);
  1044.                         uint8 ib = VDClampedRoundFixedToUint8Fast(sb);
  1045.                         uint8 ia = VDClampedRoundFixedToUint8Fast(sa);
  1046.  
  1047.                         dstp[x1] = ((uint32)ia << 24) + ((uint32)ir << 16) + ((uint32)ig << 8) + ib;
  1048.  
  1049.                         r += drdx;
  1050.                         g += dgdx;
  1051.                         b += dbdx;
  1052.                         a += dadx;
  1053.                         rhw += drhwdx;
  1054.  
  1055.                         w *= (2.0f - w*(float)rhw);
  1056.                     } while(++x1 < x2);
  1057.                 } else {
  1058.                     uint8 *dstp = (uint8 *)dstp0;
  1059.  
  1060.                     do {
  1061.                         float sg = (float)(g * w);
  1062.  
  1063.                         uint8 ig = VDClampedRoundFixedToUint8Fast(sg);
  1064.  
  1065.                         dstp[x1] = ig;
  1066.  
  1067.                         g += dgdx;
  1068.                         rhw += drhwdx;
  1069.  
  1070.                         w *= (2.0f - w*(float)rhw);
  1071.                     } while(++x1 < x2);
  1072.                 }
  1073.             }
  1074.  
  1075.             dstp0 = vdptroffset(dstp0, dstpitch);
  1076.             xl += dxl1;
  1077.             rl += drl1;
  1078.             gl += dgl1;
  1079.             bl += dbl1;
  1080.             al += dal1;
  1081.             rhwl += drhwl1;
  1082.             xr += dxr1;
  1083.             ++y;
  1084.         }
  1085.     }
  1086.  
  1087.     struct VDTriClipWorkspace {
  1088.         VDTriBltTransformedVertex *vxheapptr[2][19];
  1089.         VDTriBltTransformedVertex vxheap[21];
  1090.     };
  1091.  
  1092.     VDTriBltTransformedVertex **VDClipTriangle(VDTriClipWorkspace& ws,
  1093.                         const VDTriBltTransformedVertex *vx0,
  1094.                         const VDTriBltTransformedVertex *vx1,
  1095.                         const VDTriBltTransformedVertex *vx2,
  1096.                         int orflags) {
  1097.         // Each line segment can intersect all six planes, meaning the maximum bound is
  1098.         // 18 vertices.  Add 3 for the original.
  1099.  
  1100.         VDTriBltTransformedVertex *vxheapnext;
  1101.         VDTriBltTransformedVertex **vxlastheap = ws.vxheapptr[0], **vxnextheap = ws.vxheapptr[1];
  1102.  
  1103.         ws.vxheap[0]    = *vx0;
  1104.         ws.vxheap[1]    = *vx1;
  1105.         ws.vxheap[2]    = *vx2;
  1106.  
  1107.         vxlastheap[0] = &ws.vxheap[0];
  1108.         vxlastheap[1] = &ws.vxheap[1];
  1109.         vxlastheap[2] = &ws.vxheap[2];
  1110.         vxlastheap[3] = NULL;
  1111.  
  1112.         vxheapnext = ws.vxheap + 3;
  1113.  
  1114.         //    Current        Next        Action
  1115.         //    -------        ----        ------
  1116.         //    Unclipped    Unclipped    Copy vertex
  1117.         //    Unclipped    Clipped        Copy vertex and add intersection
  1118.         //    Clipped        Unclipped    Add intersection
  1119.         //    Clipped        Clipped        No action
  1120.  
  1121. #define    DOCLIP(cliptype, _sign_, cliparg)                \
  1122.         if (orflags & k##cliptype) {                    \
  1123.             VDTriBltTransformedVertex **src = vxlastheap;        \
  1124.             VDTriBltTransformedVertex **dst = vxnextheap;        \
  1125.                                                         \
  1126.             while(*src) {                                \
  1127.                 VDTriBltTransformedVertex *cur = *src;            \
  1128.                 VDTriBltTransformedVertex *next = src[1];        \
  1129.                                                         \
  1130.                 if (!next)                                \
  1131.                     next = vxlastheap[0];                \
  1132.                                                         \
  1133.                 if (!(cur->outcode & k##cliptype))    \
  1134.                     *dst++ = cur;                        \
  1135.                                                         \
  1136.                 if ((cur->outcode ^ next->outcode) & k##cliptype) {    \
  1137.                     double alpha = (cur->w _sign_ cur->cliparg) / ((cur->w _sign_ cur->cliparg) - (next->w _sign_ next->cliparg));    \
  1138.                                                         \
  1139.                     if (alpha >= 0.0 && alpha <= 1.0) {    \
  1140.                         vxheapnext->interp(cur, next, (float)alpha);    \
  1141.                         vxheapnext->cliparg = -(_sign_ vxheapnext->w);    \
  1142.                         *dst++ = vxheapnext++;            \
  1143.                     }                                    \
  1144.                 }                                        \
  1145.                 ++src;                                    \
  1146.             }                                            \
  1147.             *dst = NULL;                                \
  1148.             if (dst < vxnextheap+3) return NULL;        \
  1149.             src = vxlastheap; vxlastheap = vxnextheap; vxnextheap = src;    \
  1150.         }
  1151.  
  1152.  
  1153.         DOCLIP(Far, -, z);
  1154.         DOCLIP(Near, +, z);
  1155.         DOCLIP(Bottom, -, y);
  1156.         DOCLIP(Top, +, y);
  1157.         DOCLIP(Right, -, x);
  1158.         DOCLIP(Left, +, x);
  1159.  
  1160. #undef DOCLIP
  1161.  
  1162.         return vxlastheap;
  1163.     }
  1164.  
  1165.     void RenderClippedTri(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  1166.                             const VDTriBltTransformedVertex *vx0,
  1167.                             const VDTriBltTransformedVertex *vx1,
  1168.                             const VDTriBltTransformedVertex *vx2,
  1169.                             VDTriBltFilterMode filterMode,
  1170.                             bool border,
  1171.                             int orflags)
  1172.     {
  1173.  
  1174.         VDTriBltTransformedVertex *vxheapnext;
  1175.         VDTriBltTransformedVertex vxheap[21];
  1176.  
  1177.         VDTriBltTransformedVertex *vxheapptr[2][19];
  1178.         VDTriBltTransformedVertex **vxlastheap = vxheapptr[0], **vxnextheap = vxheapptr[1];
  1179.  
  1180.         vxheap[0]    = *vx0;
  1181.         vxheap[1]    = *vx1;
  1182.         vxheap[2]    = *vx2;
  1183.  
  1184.         vxlastheap[0] = &vxheap[0];
  1185.         vxlastheap[1] = &vxheap[1];
  1186.         vxlastheap[2] = &vxheap[2];
  1187.         vxlastheap[3] = NULL;
  1188.  
  1189.         vxheapnext = vxheap + 3;
  1190.  
  1191.         //    Current        Next        Action
  1192.         //    -------        ----        ------
  1193.         //    Unclipped    Unclipped    Copy vertex
  1194.         //    Unclipped    Clipped        Copy vertex and add intersection
  1195.         //    Clipped        Unclipped    Add intersection
  1196.         //    Clipped        Clipped        No action
  1197.  
  1198. #define    DOCLIP(cliptype, _sign_, cliparg)                \
  1199.         if (orflags & k##cliptype) {                    \
  1200.             VDTriBltTransformedVertex **src = vxlastheap;        \
  1201.             VDTriBltTransformedVertex **dst = vxnextheap;        \
  1202.                                                         \
  1203.             while(*src) {                                \
  1204.                 VDTriBltTransformedVertex *cur = *src;            \
  1205.                 VDTriBltTransformedVertex *next = src[1];        \
  1206.                                                         \
  1207.                 if (!next)                                \
  1208.                     next = vxlastheap[0];                \
  1209.                                                         \
  1210.                 if (!(cur->outcode & k##cliptype))    \
  1211.                     *dst++ = cur;                        \
  1212.                                                         \
  1213.                 if ((cur->outcode ^ next->outcode) & k##cliptype) {    \
  1214.                     double alpha = (cur->w _sign_ cur->cliparg) / ((cur->w _sign_ cur->cliparg) - (next->w _sign_ next->cliparg));    \
  1215.                                                         \
  1216.                     if (alpha >= 0.0 && alpha <= 1.0) {    \
  1217.                         vxheapnext->interp(cur, next, (float)alpha);    \
  1218.                         vxheapnext->cliparg = -(_sign_ vxheapnext->w);    \
  1219.                         *dst++ = vxheapnext++;            \
  1220.                     }                                    \
  1221.                 }                                        \
  1222.                 ++src;                                    \
  1223.             }                                            \
  1224.             *dst = NULL;                                \
  1225.             if (dst < vxnextheap+3) return;                \
  1226.             src = vxlastheap; vxlastheap = vxnextheap; vxnextheap = src;    \
  1227.         }
  1228.  
  1229.  
  1230.         DOCLIP(Far, -, z);
  1231.         DOCLIP(Near, +, z);
  1232.         DOCLIP(Bottom, -, y);
  1233.         DOCLIP(Top, +, y);
  1234.         DOCLIP(Right, -, x);
  1235.         DOCLIP(Left, +, x);
  1236.  
  1237. #undef DOCLIP
  1238.  
  1239.         VDTriBltTransformedVertex **src = vxlastheap+1;
  1240.  
  1241.         while(src[1]) {
  1242.             RenderTri(dst, pSources, nMipmaps, vxlastheap[0], src[0], src[1], filterMode, border);
  1243.             ++src;
  1244.         }
  1245.     }
  1246.  
  1247. }
  1248.  
  1249. bool VDPixmapTriFill(VDPixmap& dst, const uint32 c, const VDTriBltVertex *pVertices, int nVertices, const int *pIndices, int nIndices, const float pTransform[16]) {
  1250.     if (dst.format != nsVDPixmap::kPixFormat_XRGB8888)
  1251.         return false;
  1252.  
  1253.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1254.     vdfastvector<VDTriBltTransformedVertex>    xverts(nVertices);
  1255.  
  1256.     if (!pTransform)
  1257.         pTransform = xf_ident;
  1258.  
  1259.     TransformVerts(xverts.data(), pVertices, nVertices, pTransform, (float)dst.w, (float)dst.h);
  1260.  
  1261.     const VDTriBltTransformedVertex *xsrc = xverts.data();
  1262.  
  1263.     VDTriClipWorkspace clipws;
  1264.  
  1265.     while(nIndices >= 3) {
  1266.         const int idx0 = pIndices[0];
  1267.         const int idx1 = pIndices[1];
  1268.         const int idx2 = pIndices[2];
  1269.         const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1270.         const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1271.         const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1272.         const int kode0 = xv0->outcode;
  1273.         const int kode1 = xv1->outcode;
  1274.         const int kode2 = xv2->outcode;
  1275.  
  1276.         if (!(kode0 & kode1 & kode2)) {
  1277.             if (int orflags = kode0 | kode1 | kode2) {
  1278.                 VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1279.  
  1280.                 if (src) {
  1281.                     VDTriBltTransformedVertex *src0 = *src++;
  1282.  
  1283.                     // fan out triangles
  1284.                     while(src[1]) {
  1285.                         FillTri(dst, c, src0, src[0], src[1]);
  1286.                         ++src;
  1287.                     }
  1288.                 }
  1289.             } else
  1290.                 FillTri(dst, c, xv0, xv1, xv2);
  1291.         }
  1292.  
  1293.         pIndices += 3;
  1294.         nIndices -= 3;
  1295.     }
  1296.  
  1297.     return true;
  1298. }
  1299.  
  1300. bool VDPixmapTriFill(VDPixmap& dst, const VDTriColorVertex *pVertices, int nVertices, const int *pIndices, int nIndices, const float pTransform[16]) {
  1301.     VDPixmap pxY;
  1302.     VDPixmap pxCb;
  1303.     VDPixmap pxCr;
  1304.     bool ycbcr = false;
  1305.     float ycbcr_xoffset = 0;
  1306.  
  1307.     switch(dst.format) {
  1308.     case nsVDPixmap::kPixFormat_XRGB8888:
  1309.     case nsVDPixmap::kPixFormat_Y8:
  1310.         break;
  1311.     case nsVDPixmap::kPixFormat_YUV444_Planar:
  1312.     case nsVDPixmap::kPixFormat_YUV422_Planar:
  1313.     case nsVDPixmap::kPixFormat_YUV420_Planar:
  1314.     case nsVDPixmap::kPixFormat_YUV410_Planar:
  1315.         pxY.format = nsVDPixmap::kPixFormat_Y8;
  1316.         pxY.data = dst.data;
  1317.         pxY.pitch = dst.pitch;
  1318.         pxY.w = dst.w;
  1319.         pxY.h = dst.h;
  1320.  
  1321.         pxCb.format = nsVDPixmap::kPixFormat_Y8;
  1322.         pxCb.data = dst.data2;
  1323.         pxCb.pitch = dst.pitch2;
  1324.         pxCb.h = dst.h;
  1325.  
  1326.         pxCr.format = nsVDPixmap::kPixFormat_Y8;
  1327.         pxCr.data = dst.data3;
  1328.         pxCr.pitch = dst.pitch3;
  1329.         pxCr.h = dst.h;
  1330.  
  1331.         if (dst.format == nsVDPixmap::kPixFormat_YUV410_Planar) {
  1332.             pxCr.w = pxCb.w = dst.w >> 2;
  1333.             pxCr.h = pxCb.h = dst.h >> 2;
  1334.         } else if (dst.format == nsVDPixmap::kPixFormat_YUV420_Planar) {
  1335.             pxCr.w = pxCb.w = dst.w >> 1;
  1336.             pxCr.h = pxCb.h = dst.h >> 1;
  1337.             ycbcr_xoffset = 0.5f / (float)pxCr.w;
  1338.         } else if (dst.format == nsVDPixmap::kPixFormat_YUV422_Planar) {
  1339.             pxCr.w = pxCb.w = dst.w >> 1;
  1340.             ycbcr_xoffset = 0.5f / (float)pxCr.w;
  1341.         }
  1342.  
  1343.         ycbcr = true;
  1344.         break;
  1345.     default:
  1346.         return false;
  1347.     }
  1348.  
  1349.     vdfastvector<VDTriBltTransformedVertex>    xverts(nVertices);
  1350.  
  1351.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1352.     if (!pTransform)
  1353.         pTransform = xf_ident;
  1354.  
  1355.     TransformVerts(xverts.data(), pVertices, nVertices, pTransform, (float)dst.w, (float)dst.h);
  1356.  
  1357.     const VDTriBltTransformedVertex *xsrc = xverts.data();
  1358.  
  1359.     VDTriClipWorkspace clipws;
  1360.  
  1361.     while(nIndices >= 3) {
  1362.         const int idx0 = pIndices[0];
  1363.         const int idx1 = pIndices[1];
  1364.         const int idx2 = pIndices[2];
  1365.         const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1366.         const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1367.         const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1368.         const int kode0 = xv0->outcode;
  1369.         const int kode1 = xv1->outcode;
  1370.         const int kode2 = xv2->outcode;
  1371.  
  1372.         if (!(kode0 & kode1 & kode2)) {
  1373.             if (int orflags = kode0 | kode1 | kode2) {
  1374.                 VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1375.  
  1376.                 if (src) {
  1377.                     VDTriBltTransformedVertex *src0 = *src++;
  1378.  
  1379.                     // fan out triangles
  1380.                     if (ycbcr) {
  1381.                         while(src[1]) {
  1382.                             VDTriBltTransformedVertex t0 = *src0;
  1383.                             VDTriBltTransformedVertex t1 = *src[0];
  1384.                             VDTriBltTransformedVertex t2 = *src[1];
  1385.  
  1386.                             FillTriGrad(pxY, &t0, &t1, &t2);
  1387.                             t0.g = t0.b;
  1388.                             t1.g = t1.b;
  1389.                             t2.g = t2.b;
  1390.                             FillTriGrad(pxCb, &t0, &t1, &t2);
  1391.                             t0.g = t0.r;
  1392.                             t1.g = t1.r;
  1393.                             t2.g = t2.r;
  1394.                             FillTriGrad(pxCr, &t0, &t1, &t2);
  1395.  
  1396.                             ++src;
  1397.                         }
  1398.                     } else {
  1399.                         while(src[1]) {
  1400.                             FillTriGrad(dst, src0, src[0], src[1]);
  1401.                             ++src;
  1402.                         }
  1403.                     }
  1404.                 }
  1405.             } else {
  1406.                 if (ycbcr) {
  1407.                     VDTriBltTransformedVertex t0 = *xv0;
  1408.                     VDTriBltTransformedVertex t1 = *xv1;
  1409.                     VDTriBltTransformedVertex t2 = *xv2;
  1410.  
  1411.                     FillTriGrad(pxY, &t0, &t1, &t2);
  1412.                     t0.x += t0.w*ycbcr_xoffset;
  1413.                     t0.g = t0.b;
  1414.                     t1.x += t1.w*ycbcr_xoffset;
  1415.                     t1.g = t1.b;
  1416.                     t2.x += t2.w*ycbcr_xoffset;
  1417.                     t2.g = t2.b;
  1418.                     FillTriGrad(pxCb, &t0, &t1, &t2);
  1419.                     t0.g = t0.r;
  1420.                     t1.g = t1.r;
  1421.                     t2.g = t2.r;
  1422.                     FillTriGrad(pxCr, &t0, &t1, &t2);
  1423.                 } else {
  1424.                     FillTriGrad(dst, xv0, xv1, xv2);
  1425.                 }
  1426.             }
  1427.         }
  1428.  
  1429.         pIndices += 3;
  1430.         nIndices -= 3;
  1431.     }
  1432.  
  1433.     return true;
  1434. }
  1435.  
  1436. bool VDPixmapTriBlt(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  1437.                     const VDTriBltVertex *pVertices, int nVertices,
  1438.                     const int *pIndices, int nIndices,
  1439.                     VDTriBltFilterMode filterMode,
  1440.                     bool border,
  1441.                     const float pTransform[16])
  1442. {
  1443.     if (dst.format != nsVDPixmap::kPixFormat_XRGB8888)
  1444.         return false;
  1445.  
  1446.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1447.     vdfastvector<VDTriBltTransformedVertex>    xverts(nVertices);
  1448.  
  1449.     if (!pTransform)
  1450.         pTransform = xf_ident;
  1451.  
  1452.     TransformVerts(xverts.data(), pVertices, nVertices, pTransform, (float)dst.w, (float)dst.h);
  1453.  
  1454.     const VDTriBltTransformedVertex *xsrc = xverts.data();
  1455.  
  1456.     VDTriClipWorkspace clipws;
  1457.  
  1458.     while(nIndices >= 3) {
  1459.         const int idx0 = pIndices[0];
  1460.         const int idx1 = pIndices[1];
  1461.         const int idx2 = pIndices[2];
  1462.         const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1463.         const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1464.         const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1465.         const int kode0 = xv0->outcode;
  1466.         const int kode1 = xv1->outcode;
  1467.         const int kode2 = xv2->outcode;
  1468.  
  1469.         if (!(kode0 & kode1 & kode2)) {
  1470.             if (int orflags = kode0 | kode1 | kode2) {
  1471.                 VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1472.  
  1473.                 if (src) {
  1474.                     VDTriBltTransformedVertex *src0 = *src++;
  1475.  
  1476.                     // fan out triangles
  1477.                     while(src[1]) {
  1478.                         RenderTri(dst, pSources, nMipmaps, src0, src[0], src[1], filterMode, border);
  1479.                         ++src;
  1480.                     }
  1481.                 }
  1482.             } else
  1483.                 RenderTri(dst, pSources, nMipmaps, xv0, xv1, xv2, filterMode, border);
  1484.         }
  1485.  
  1486.         pIndices += 3;
  1487.         nIndices -= 3;
  1488.     }
  1489.  
  1490.     return true;
  1491. }
  1492.  
  1493. ///////////////////////////////////////////////////////////////////////////
  1494.  
  1495. void VDPixmapSetTextureBorders(VDPixmap& px, bool wrap) {
  1496.     const int w = px.w;
  1497.     const int h = px.h;
  1498.  
  1499.     VDPixmapBlt(px, 0,   1,   px, wrap ? w-2 : 1, 1,              1, h-2);
  1500.     VDPixmapBlt(px, w-1, 1,   px, wrap ? 1 : w-2, 1,              1, h-2);
  1501.  
  1502.     VDPixmapBlt(px, 0,   0,   px, 0,              wrap ? h-2 : 1, w, 1);
  1503.     VDPixmapBlt(px, 0,   h-1, px, 0,              wrap ? 1 : h-2, w, 1);
  1504. }
  1505.  
  1506. ///////////////////////////////////////////////////////////////////////////
  1507.  
  1508. VDPixmapTextureMipmapChain::VDPixmapTextureMipmapChain(const VDPixmap& src, bool wrap, int maxlevels) {
  1509.     int w = src.w;
  1510.     int h = src.h;
  1511.     int mipcount = 0;
  1512.  
  1513.     while((w>1 || h>1) && maxlevels--) {
  1514.         ++mipcount;
  1515.         w >>= 1;
  1516.         h >>= 1;
  1517.     }
  1518.  
  1519.     mBuffers.resize(mipcount);
  1520.     mMipMaps.resize(mipcount);
  1521.  
  1522.     for(int mip=0; mip<mipcount; ++mip) {
  1523.         const int mipw = ((src.w-1)>>mip)+1;
  1524.         const int miph = ((src.h-1)>>mip)+1;
  1525.  
  1526.         mMipMaps[mip] = &mBuffers[mip];
  1527.         mBuffers[mip].init(mipw+2, miph+2, nsVDPixmap::kPixFormat_XRGB8888);
  1528.  
  1529.         if (!mip) {
  1530.             VDPixmapBlt(mBuffers[0], 1, 1, src, 0, 0, src.w, src.h);
  1531.         } else {
  1532.             const VDPixmap& prevmip = mBuffers[mip-1];
  1533.  
  1534.             VDPixmapStretchBltBilinear(mBuffers[mip], 1<<16, 1<<16, (mipw+1)<<16, (miph+1)<<16, prevmip, 1<<16, 1<<16, (prevmip.w-1)<<16, (prevmip.h-1)<<16);
  1535.         }
  1536.         VDPixmapSetTextureBorders(mBuffers[mip], wrap);
  1537.     }
  1538. }
  1539.  
  1540.